home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / ge_cool.lha / GE_COOL2.1 / src / Envelope / Envelope.h next >
C/C++ Source or Header  |  1992-05-25  |  10KB  |  273 lines

  1. // 
  2. // Copyright (C) 1992 General Electric Company.  
  3. // 
  4. // Permission is granted to any individual or institution to use, copy, modify, 
  5. // and distribute this software, provided that this complete copyright and 
  6. // permission notice is maintained, intact, in all copies and supporting
  7. // documentation.  
  8. // 
  9. // General Electric Company 
  10. // provides this software "as is" without express or implied warranty.  
  11. // 
  12. // Created: VDN 05/13/92 -- Initial design with ATT.
  13. //
  14. // This envelope is a generic template, has no data, publicly inherits
  15. // from the letter, and wraps outside a letter so that we can redefine 
  16. // the copy constructor to do a shallow copy instead of a deep copy,
  17. // when a return by value is required. 
  18. //
  19. // Such returns by value occur for example in: 
  20. // Matrix a, b, c; 
  21. // c = (a + b) + c; 
  22. // Note that the sum of a and b, (a+b), has to be deleted by the compiler,
  23. // and this requires (a+b) being returned by value. Return by value will
  24. // call the copy constructor of matrix, and so does a deep copy. 
  25. // There is one more copy at the assignment =. 
  26. // Note that the compiler generates temporary handles to the objects returned
  27. // by value and delete these objects when the current scope is exited.
  28. //
  29. // Arithmetic operations such as: +, -, *, /, %, and logical operations such 
  30. // as: |, &, ^ are overloaded to take envelopes, to avoid unecessary copying. 
  31. // Arithmetic, logical, shift operations are assumed non symmetric in general.
  32. //
  33. // Sometimes, the mutators +=, -=, ..., can be done without temporary memory,
  34. // such as matrix addition and negation, string concatenation, etc..
  35. // In these cases, use the flag ENVELOPE_* to generate versions of +, 
  36. // based on +=, etc... 
  37. // Note that, the envelope is a macro rather than a parameterized
  38. // template, to allow expansion of member functions as needed.
  39. //
  40. // This is an implementation of Coplien's envelope-letter idiom, 
  41. // that do not require reimplementation of the letter's member functions 
  42. // at the envelope level.
  43. // References: 
  44. // 1. Coplien (1992) Advanced C++ programming styles and idioms. 
  45. //    Addison-Wesley.
  46.  
  47.  
  48.  
  49. // Remember to include the letter class before this point.
  50. // #include <cool/CoolLetter.h>
  51.  
  52. class CoolEnvelope : public CoolLetter {    // Inherit all from class CoolLetter
  53. friend class CoolLetter;            
  54.  
  55. public:                        
  56.   inline CoolEnvelope();            // Empty Constructor
  57.   inline CoolEnvelope(CoolEnvelope&);        // Copy constructor
  58.   inline ~CoolEnvelope();            // Destructor
  59.  
  60.   inline operator CoolLetter& ();        // Conversion to letter
  61.   inline operator CoolLetter& () const;        
  62.  
  63.   inline friend ostream& operator<< (ostream&, const CoolEnvelope&); 
  64.   inline friend ostream& operator<< (ostream&, const CoolEnvelope*);
  65.  
  66.   // should be defined as member function of Letter class
  67.   // inline friend CoolLetter& operator= (CoolLetter&, CoolEnvelope&);
  68.  
  69.   // Defining operator + based on += with these macros, 
  70.   // if and only if += can be done in place, like += of matrices.
  71.  
  72. #define DECLARE_ENVELOPE_OPERATOR(op)                                      \
  73.   inline friend CoolEnvelope operator op (const CoolLetter&, const CoolLetter&); \
  74.   inline friend CoolEnvelope operator op (const CoolLetter&, const CoolEnvelope&);\
  75.   inline friend CoolEnvelope& operator op (CoolEnvelope&, const CoolLetter&);     \
  76.   inline friend CoolEnvelope& operator op (CoolEnvelope&, const CoolEnvelope&); 
  77.  
  78.   // Arithmetic operators
  79. #ifdef ENVELOPE_PLUS                // iff operator+= can be in place 
  80.   DECLARE_ENVELOPE_OPERATOR(+)
  81. #endif
  82. #ifdef ENVELOPE_MINUS                // iff operator-= can be in place 
  83.   DECLARE_ENVELOPE_OPERATOR(-)
  84. #endif
  85. #ifdef ENVELOPE_STAR                // iff operator*= can be in place 
  86.   DECLARE_ENVELOPE_OPERATOR(*)
  87. #endif
  88. #ifdef ENVELOPE_SLASH                // iff operator/= can be in place 
  89.   DECLARE_ENVELOPE_OPERATOR(/)
  90. #endif
  91. #ifdef ENVELOPE_PERCENT                // iff operator%= can be in place 
  92.   DECLARE_ENVELOPE_OPERATOR(%)
  93. #endif
  94.  
  95.   // Logical operators
  96. #ifdef ENVELOPE_VERTICAL                        // iff operator|= can be in place
  97.   DECLARE_ENVELOPE_OPERATOR(|)
  98. #endif
  99. #ifdef ENVELOPE_AMPERSAND            // iff operator&= can be in place
  100.   DECLARE_ENVELOPE_OPERATOR(&)
  101. #endif
  102. #ifdef ENVELOPE_CARET                // iff operator^= can be in place
  103.   DECLARE_ENVELOPE_OPERATOR(^)
  104. #endif
  105.  
  106.   // Shift operators
  107. #ifdef ENVELOPE_DOUBLE_LEFT_BRACKET        // iff operator<<= can be in place
  108.   DECLARE_ENVELOPE_OPERATOR(<<)    
  109. #endif
  110. #ifdef ENVELOPE_DOUBLE_RIGHT_BRACKET        // iff operator>>= can be in place
  111.   DECLARE_ENVELOPE_OPERATOR(>>)
  112. #endif
  113.  
  114. #undef DECLARE_ENVELOPE_OPERATOR        
  115.  
  116. protected:
  117.   inline void shallow_swap (CoolEnvelope*, CoolEnvelope*);
  118. };                        
  119.  
  120. // Envelope() -- Empty constructor creates an envelope wrapping an empty letter
  121. // Input:     none
  122. // Ouput:     envelope reference
  123.  
  124. inline CoolEnvelope::CoolEnvelope() 
  125. : CoolLetter()                    // create empty letter inside
  126. {}                        // nothing for envelope
  127.  
  128.  
  129. // Envelope() -- Copy constructor, swapping the contents of letter over.
  130. // Input:     envelope wraping a non null letter
  131. // Ouput:     envelope with contents of letter being swapped over.
  132.  
  133. inline CoolEnvelope::CoolEnvelope(CoolEnvelope& env) {
  134.   this->shallow_swap (this, &env);        // swap contents over
  135. }
  136.  
  137. // ~Envelope() -- Destructor, destroy letter too if non null.
  138. // Input:     none
  139. // Output:    none
  140.  
  141. inline CoolEnvelope::~CoolEnvelope() {}        // delete letter by inherit.
  142.  
  143.  
  144. // operator Letter&() -- Automatic conversion to letter, if necessary.
  145. // Input:     envelope reference
  146. // Ouput:     letter reference
  147.  
  148. inline CoolEnvelope::operator CoolLetter& () {
  149.   return *((CoolLetter*) this);            // same physical entity.
  150. }
  151.  
  152. inline CoolEnvelope::operator CoolLetter& () const {
  153.   return *((CoolLetter*) this);            // const version of above
  154. }
  155.  
  156.  
  157. // operator=  -- Assignment from a envelope back to real letter.
  158. //               Should be defined in CoolLetter class, not here.
  159. // Input:     envelope reference
  160. // Output:    letter reference with contents in envelope being swapped over
  161. // 
  162. // inline CoolLetter& operator= (CoolLetter& let, CoolEnvelope& env) {
  163. //   shallow_swap ((CoolEnvelope*) &let, &env);  // same physical layout
  164. //   return let;
  165. // }        
  166.  
  167. // shallow_swap() -- Swap contents by doing shallow copy of bytes.
  168. // Input:    pointer to two envelopes
  169. // Output:   none, contents of envelopes are swapped.
  170.  
  171. void CoolEnvelope::shallow_swap (CoolEnvelope* env1, CoolEnvelope* env2) {
  172.   int n = sizeof(CoolEnvelope);            // n = sizeof(CoolLetter)
  173.   char* temp = new char[n];            // temporary space for swap
  174.   char* env1_contents = (char*) env1;        // copy n bytes starting from ptr
  175.   char* env2_contents = (char*) env2;    
  176.   memcpy(temp, env1_contents, n);        // shallow swap the contents of
  177.   memcpy(env1_contents, env2_contents, n);    // env1 and env2
  178.   memcpy(env2_contents, temp, n);
  179.   delete [] temp;                // free temp space for swap
  180. }
  181.  
  182. // operator<<  -- Overload output operator to print envelope
  183. // Input:    os, envelope reference
  184. // Output:   os
  185.  
  186. inline ostream& operator<< (ostream& os, const CoolEnvelope& env) {
  187.   return os << *((CoolLetter*) &env);
  188. }
  189.  
  190. // operator<<  -- Overload output operator to print envelope
  191. // Input:    os, envelope pointer
  192. // Output:   os
  193.  
  194. inline ostream& operator<< (ostream& os, const CoolEnvelope* env) {
  195.   return os << *((CoolLetter*) env);
  196. }
  197.  
  198.  
  199. // operator op -- Use operator op_equal, and return an envelope by value
  200. //                so that deep copy of the object is avoided.
  201. //                For generality, operations are assumed non symmetric.
  202. // Input:    type reference, envelope reference, all 4 permutations.
  203. // Output:   envelope returned by value
  204.  
  205.  
  206. #define IMPLEMENT_ENVELOPE_OPERATOR(op,op_equal)                  \
  207. inline CoolEnvelope operator op (const CoolLetter& arg1, const CoolLetter& arg2) {\
  208.   CoolLetter temp(arg1);                    /*Deep copy of arg1*/         \
  209.   temp op_equal arg2;                /*Mutate with op arg2*/       \
  210.   CoolEnvelope& result = *((CoolEnvelope*) &temp);/*Same physical object*/    \
  211.   return result;                /*Copy envelope only*/          \
  212. }                                          \
  213.                                           \
  214. inline CoolEnvelope operator op (const CoolLetter& arg1, const CoolEnvelope& arg2){\
  215.   CoolLetter temp(arg1);                    /*Deep copy of arg1*/         \
  216.   temp op_equal *((CoolLetter*) &arg2);        /*Mutate with op arg2*/       \
  217.   CoolEnvelope& result = *((CoolEnvelope*) &temp);/*Same physical object*/    \
  218.   return result;                /*Copy envelope only*/          \
  219. }                                          \
  220.                                           \
  221. inline CoolEnvelope& operator op (CoolEnvelope& arg1, const CoolLetter& arg2) {\
  222.   CoolLetter& temp = *((CoolLetter*) &arg1);    /*Reuse arg1*/              \
  223.   temp op_equal arg2;                /*Mutate in place*/          \
  224.   return arg1;                    /*Envelope not copied*/          \
  225. }                                          \
  226.                                           \
  227. inline CoolEnvelope& operator op (CoolEnvelope& arg1, const CoolEnvelope& arg2) {\
  228.   CoolLetter& temp = *((CoolLetter*) &arg1);    /*Reuse arg1*/              \
  229.   temp op_equal *((CoolLetter*) &arg2);        /*Mutate in place*/          \
  230.   return arg1;                    /*Envelope not copied*/          \
  231. }                                          
  232.  
  233.   // Arithmetic operators:
  234. #ifdef ENVELOPE_PLUS                // iff operator+= can be in place
  235.   IMPLEMENT_ENVELOPE_OPERATOR(+,+=)
  236. #endif
  237.  
  238. #ifdef ENVELOPE_MINUS                // iff operator-= can be in place
  239.   IMPLEMENT_ENVELOPE_OPERATOR(-,-=)
  240. #endif
  241. #ifdef ENVELOPE_STAR                // iff operator*= can be in place
  242.   IMPLEMENT_ENVELOPE_OPERATOR(*,*=)
  243. #endif
  244. #ifdef ENVELOPE_SLASH                // iff operator/= can be in place
  245.   IMPLEMENT_ENVELOPE_OPERATOR(/,/=)
  246. #endif
  247. #ifdef ENVELOPE_PERCENT                // iff operator%= can be in place
  248.   IMPLEMENT_ENVELOPE_OPERATOR(%,%=)
  249. #endif
  250.  
  251.   // Logical operators:
  252. #ifdef ENVELOPE_VERTICAL            // iff operator|= can be in place
  253.   IMPLEMENT_ENVELOPE_OPERATOR(|,|=)
  254. #endif
  255. #ifdef ENVELOPE_AMPERSAND            // iff operator&= can be in place
  256.   IMPLEMENT_ENVELOPE_OPERATOR(&,&=)
  257. #endif
  258. #ifdef ENVELOPE_CARET                // iff operator^= can be in place
  259.   IMPLEMENT_ENVELOPE_OPERATOR(^,^=)
  260. #endif
  261.  
  262.   // Shift operators:
  263. #ifdef ENVELOPE_DOUBLE_LEFT_BRACKET        // iff operator<<= can be in place
  264.   IMPLEMENT_ENVELOPE_OPERATOR(<<,<<=)
  265. #endif
  266. #ifdef ENVELOPE_DOUBLE_RIGHT_BRACKET        // iff operator>>= can be in place
  267.   IMPLEMENT_ENVELOPE_OPERATOR(>>,>>=)
  268. #endif
  269.  
  270. #undef IMPLEMENT_ENVELOPE_OPERATOR        // Delete macro definition
  271.  
  272.  
  273.